Callbacks API用来管理回调函数,也作为deferred延迟对象的基础部分,今天就一起来探寻它的源码(对应src下的callbacks.js)。
代码挂在我的github上,对应文件夹v0.5.1。
https://github.com/zrysmt/DIY-zepto
注:要在github源代码中自己编译的话,要在基础包命令:npm run dist
上要进行扩展了,输入命令:
1 | MODULES="zepto event ajax callbacks" npm run dist |
1.示例Demo
1 | var foo = function(value) { |
示例1:1
2
3
4
5
6
7
8var callbacks = $.Callbacks();
callbacks.add(foo);
callbacks.fire(['hello', 'wo', '123']);
callbacks.add(bar);
callbacks.fire('中');
/*foo:hello,wo,123
foo:中
bar:中*/
标记:
- once: 回调只能触发一次
- memory 记录上一次触发回调函数列表时的参数,之后添加的函数都用这参数立即执行
- unique 一个回调函数只能被添加一次
- stopOnFalse 当某个回调函数返回false时中断执行
示例2:1
2
3
4
5
6
7
8var callbacks = $.Callbacks({
memory: true
});
callbacks.add(foo);
callbacks.fire(['hello', 'wo', '123']);
callbacks.add(bar);
/*foo:hello,wo,123
bar:hello,wo,123*/
示例3:1
2
3
4
5
6
7
8
9
10var callbacks = $.Callbacks({
memory: true,
once: true //只能执行一次
});
callbacks.add(foo);
callbacks.fire(['hello', 'wo', '123']);
callbacks.add(bar);
callbacks.fire(['hello', 'wo', '123']);
/*foo:hello,wo,123
bar:hello,wo,123*/
2.整体结构
1 | var Callbacks = function($) { |
3.源码
当然你也可以结合下一部分的过程分析,来理解源码。
3.1 几个重要变量
1 | options = $.extend({}, options); |
3.2 fire函数– 回调底层函数
1 | /** |
3.3 Callbacks对象
回调函数管理:添加add() 移除remove()、触发fire()、锁定lock()、禁用disable()回调函数。它为Deferred异步队列提供支持。
原理:通过一个数组保存回调函数,其他方法围绕此数组进行检测和操作
1 | Callbacks = { |
4.过程分析
对于第一部分的示例:1
2
3var callbacks = $.Callbacks();
callbacks.add(foo);
callbacks.fire(['hello', 'wo', '123']);
- add方法(CallBacks.add方法)
- add函数(
add(arguments)
)
$.each可以处理参数是数组的形式- 非数组 直接存放到list中
list.push(arg)
; - 数组 递归
add(arg)
- 非数组 直接存放到list中
- 如果memory存在,为ture,离开执行 (
fire(memory)
) - 返回this,可以链式调用
- add函数(
- fire方法(CallBacks.fire方法)
- Callbacks.fireWith(this, arguments)
- 未回调过,非锁定、禁用时
- 处理参数,包装成数组`args = [context, args.slice ? args.slice() : args]
- 如果正在执行回调(
firing = true
)stack.push(args);//正在回调中,存入stack
- 否则 调用外层fire函数,立即执行。
- 未回调过,非锁定、禁用时
- Callbacks.fireWith(this, arguments)
外层fire函数
参数处理
1
2
3
4
5
6memory = options.memory && data;
fired = true;
firingIndex = firingStart || 0;
firingStart = 0;
firingLength = list.length;
firing = true; //正在回调遍历回调函数执行 for循环
- 如果 list[ firingIndex ] 为false,且stopOnFalse(中断)模式
立即中断memory = false; break;
- 否则,立刻执行
list[firingIndex].apply(data[0], data[1])
- 如果 list[ firingIndex ] 为false,且stopOnFalse(中断)模式
- 处理结束 firing = false; //回调执行完毕
- option.once为false,即stack为true
stack.length && fire(stack.shift()); //执行stack里的回调 - option.memory存在 则清空list【此时已经执行完结束了】
- 其余情况,包括option.once为true,在遍历回调函数中已经执行过了,这里禁用回掉即可
Callbacks.disable();
全部代码挂在我的github上,本博文对应文件夹v0.5.x。
https://github.com/zrysmt/DIY-zepto
参考阅读: